#pragma once

#include "Shader.h"

#include "MaterialShader.h"

namespace RenderSystem
{
	class MeshMaterialShaderType
		: public ShaderType
	{
	public:

		struct CompiledShaderInitializerType : MaterialShaderType::CompiledShaderInitializerType
		{
			CompiledShaderInitializerType(
				ShaderType* InType,
				const ShaderCompilerOutput& CompilerOutput,
				const Material* InMaterial,
				class VertexFactoryType* pInVertexFactoryType
				):
			MaterialShaderType::CompiledShaderInitializerType(InType,CompilerOutput,InMaterial),
				m_pVertexFactoryType(pInVertexFactoryType)
			{}

			VertexFactoryType* m_pVertexFactoryType;
		};

		typedef Shader* (*ConstructCompiledType)( const CompiledShaderInitializerType& );

		MeshMaterialShaderType(
			const TCHAR* InName,
			const TCHAR* InSourceFilename,
			const TCHAR* InFunctionName,
			ConstructSerializedType InConstructSerializedRef,
			ConstructCompiledType	InConstructCompiledRef,
			ModifyCompilationEnvironmentType InModifyCompilationEnvironmentRef
			):ShaderType(InName,InSourceFilename,InFunctionName,InConstructSerializedRef,InModifyCompilationEnvironmentRef),
			m_funConstructCompiledType(InConstructCompiledRef)
		{}
		virtual ~MeshMaterialShaderType(void);

		/**
		* Enqueues a compilation for a new shader of this type.
		* @param Platform - The platform to compile for.
		* @param Material - The material to link the shader with.
		* @param MaterialShaderCode - The shader code for the material.
		* @param VertexFactoryType - The vertex factory to compile with.
		*/
		void BeginCompileShader(
			const ShaderProfile& rShaderProfile,
			const Material* pMaterial,
			const TCHAR* pszMaterialShaderCode,
			VertexFactoryType* pVertexFactoryType
			);

		Shader* FinishCompileShader( const Material* pMaterial, const ShaderCompileJob& rCurrentJob );

		virtual MeshMaterialShaderType* GetMeshMaterialShaderType() { return this; }

	private:

		ConstructCompiledType	m_funConstructCompiledType;
	};

	class MeshMaterialShaderMap : public TShaderMap<MeshMaterialShaderType>
	{
	public:
		MeshMaterialShaderMap(void);
		virtual ~MeshMaterialShaderMap(void);

		/**
		* Enqueues compilation for all shaders for a material and vertex factory type.
		* @param Material - The material to compile shaders for.
		* @param MaterialShaderCode - The shader code for Material.
		* @param VertexFactoryType - The vertex factory type to compile shaders for.
		* @param Platform - The platform to compile for.
		*/
		void BeginCompile(
			const Material* pMaterial,
			const TCHAR* pszMaterialShaderCode,
			VertexFactoryType* pVertexFactoryType,
			const ShaderProfile& rShaderProfile
			);

		/**
		* Creates shaders for all of the compile jobs and caches them in this shader map.
		* @param Material - The material to compile shaders for.
		* @param CompilationResults - The compile results that were enqueued by BeginCompile.
		*/
		void FinishCompile(const Material* Material, const ShaderCompileJobs& rShaderCompileJobs );

		VertexFactoryType* GetVertexFactory(void) { return m_pVertexFactoryType; }

	private:

		VertexFactoryType* m_pVertexFactoryType;
	};
}